package com.bc004346.travelus;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.SystemClock;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.Toast;

import com.bc004346.travelus.DataAccess.AsyncTasks.GetProfileTaskFragment;
import com.bc004346.travelus.DataAccess.AsyncTasks.LoginTaskFragment;
import com.bc004346.travelus.DataAccess.SQLHelper;
import com.bc004346.travelus.DataAccess.TravelUsScreenScraper;
import com.bc004346.travelus.Model.Abstract.FlightListActivity;
import com.bc004346.travelus.Model.Domain.Reservation;
import com.bc004346.travelus.Model.Interface.IGetProfileCallback;
import com.bc004346.travelus.Model.Interface.ILoginCallback;
import com.bc004346.travelus.Model.TravelUsException;
import com.bc004346.travelus.Utility.Utility;

import java.util.Date;
import java.util.List;

import static com.bc004346.travelus.Utility.Utility.HOUR;
import static com.bc004346.travelus.Utility.Utility.SHORT_TIME;
import static com.bc004346.travelus.Utility.Utility.log;

/**
 * Created by Renats on 9/4/2014.
 * The new flight list activity
 */
public class MyFlightListActivity
        extends FlightListActivity
        implements ILoginCallback, IGetProfileCallback/*, ICheckinCallback*/ {

    public static final String LOGIN_TASK_TAG = "loginTask";
    //public static final String CHECKIN_TASK_TAG = "checkinTask";
    //public static final String CHECKIN_INTENT = "com.bc004346.travelus.checkin";
    public static final String PNR_REFRESH_INTENT = "com.bc004346.travelus.pnrRefresh";
    public static final String EXTRA_FLIGHT = "FLIGHT";
    public static final int LOGIN_REQUEST_CODE = 1000;
    private ProgressBar mProgressBar;
    private SQLHelper mSqlHelper;
    //private PendingIntent mPendingCheckinIntent;
    private PendingIntent mPendingPnrRefreshIntent;
    //private BroadcastReceiver mBroadcastCheckinReceiver;
    private BroadcastReceiver mBroadcastPnrRefreshCheckinReceiver;
    private AlarmManager mAlarmManager;
    private TravelUsScreenScraper mTravelUs;
    private Context mContext;

    //<editor-fold desc="Properties">

    public SQLHelper getSqlHelper() {
        if (mSqlHelper == null) {
            mSqlHelper = new SQLHelper(getApplicationContext());
        }
        return mSqlHelper;
    }

    //</editor-fold>

    @Override
    protected void onDestroy() {
        super.onDestroy();
        try {
            //mAlarmManager.cancel(mPendingCheckinIntent);
            mAlarmManager.cancel(mPendingPnrRefreshIntent);

//            if (mBroadcastCheckinReceiver != null)
//                unregisterReceiver(mBroadcastCheckinReceiver);
            if (mBroadcastPnrRefreshCheckinReceiver != null)
                unregisterReceiver(mBroadcastPnrRefreshCheckinReceiver);

        } catch (Exception e) {
            Utility.log(e.toString());
            mStatus.setText(e.getMessage());
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        try {
            mTopProgressBar.setVisibility(View.INVISIBLE);
            mAlarmManager = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);

            mContext = getApplicationContext();
            //setupAsyncLogin();
            setupAsyncPnrRefresh();

            mProgressBar = (ProgressBar) findViewById(R.id.mainActivityProgressBar);

            if (Utility.username.isEmpty() || Utility.password.isEmpty())
                startLoginActivity();
            else {
                LoginTaskFragment mLoginTaskFragment = (LoginTaskFragment) getFragmentManager().findFragmentByTag(LOGIN_TASK_TAG);

                if (savedInstanceState != null)
                    mFragment.refresh(getSqlHelper().selectReservations());
                else if (mLoginTaskFragment == null) {
                    mStatus.setText(getString(R.string.common_logging_in));
                    mLoginTaskFragment = LoginTaskFragment.newInstance(Utility.username, Utility.password);
                    getFragmentManager().beginTransaction().add(mLoginTaskFragment, LOGIN_TASK_TAG).commit();
                }
            }
            mTravelUs = Utility.getInstance().getTravelUS();
        } catch (Exception e) {
            Utility.log(e.toString());
            if (mStatus != null)
                mStatus.setText(e.getMessage());
            if (mTopProgressBar != null)
                mTopProgressBar.setVisibility(View.INVISIBLE);
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent resultIntent) {
        try {

            mTopProgressBar.setVisibility(View.INVISIBLE);
            switch (requestCode) {
                case LOGIN_REQUEST_CODE:
                    if (resultCode == RESULT_OK)
                        refresh();
                    else
                        finish();
                    break;
            }
        } catch (Exception e) {
            Utility.log(e.toString());
            mStatus.setText(e.getMessage());
        }
    }

    @Override
    protected void onStop() {
        Utility.onStop(this);
        super.onStop();
    }

    @Override
    public void onLoginPostExecute(Boolean success, Exception e) {
        try {
            if (e != null) {
                if (e.getClass() == TravelUsException.class)
                    mStatus.setText(e.getMessage());
                else
                    mStatus.setText(String.format(getString(R.string.common_login_has_failed), e.getMessage()));
                mTopProgressBar.setVisibility(View.INVISIBLE);
                log(e, this);
            } else if (success) {
                mStatus.setText("");
                long target = Utility.pnrRefreshDate.getTime() + Long.valueOf(Utility.pnrRefreshInterval()) * HOUR;
                if (target <= new Date().getTime())
                    refresh();
                else {
                    mTopProgressBar.setVisibility(View.INVISIBLE);
                    mFragment.refresh(getSqlHelper().selectReservations());
                    schedulePnrRefresh(new Date(target));
                }
            } else {
                mStatus.setText(getString(R.string.dashboardStatus_LoginFailed));
                mTopProgressBar.setVisibility(View.INVISIBLE);
                startLoginActivity();
            }
        } catch (NumberFormatException e1) {
            Utility.log(e1.toString());
            mStatus.setText(e1.getMessage());
            mTopProgressBar.setVisibility(View.INVISIBLE);
        }
    }

    @Override
    public void onGetProfilePostExecute(List<Reservation> reservations, Exception e) {

        try {
            mTopProgressBar.setVisibility(View.INVISIBLE);
            mProgressBar.setProgress(0);
            removeTaskFragment();

            if (e != null) {
                mStatus.setText(e.getMessage());
                log(e, this);
            } else {
                if (reservations == null || reservations.size() == 0) {
                    mStatus.setText(getString(R.string.common_no_flights_found));
                    return;
                }

                Utility.name = mTravelUs.getName();
                Utility.badge = mTravelUs.getBadge();
                Utility.seniority = mTravelUs.getSeniority();

                getSqlHelper().MergeReservations(reservations);
                mFragment.refresh(getSqlHelper().selectReservations());

                //            if (Utility.autoCheckinEnabled())
                //                processFlightsReadyForCheckin(reservations);

                mStatus.setText("");
                schedulePnrRefresh(new Date(new Date().getTime() + Long.valueOf(Utility.pnrRefreshInterval()) * HOUR));
                Utility.pnrRefreshDate = new Date();
            }
        } catch (NumberFormatException e1) {
            Utility.log(e1.toString());
            mStatus.setText(e1.getMessage());
        }
    }

    @Override
    public void onGetProfileProgressUpdate(String... update) {
        try {
            mProgressBar.setProgress(Integer.valueOf(update[0]));
            String s = update[1];
            mStatus.setText(s);
        } catch (NumberFormatException e) {
            Utility.log(e.toString());
            mStatus.setText(e.getMessage());
        }
    }

//    @Override
//    public void onCheckinPostExecute(Flight flight, Exception e) {
//
//        try {
//            String message;
//
//            if (e != null) {
//                message = String.format(getString(R.string.dashboardStatus_ErrorCheckingIn),
//                        flight.toString(),
//                        e.toString());
//                log(e, this);
//            } else if (flight == null)
//                message = getString(R.string.dashboardStatus_FlightObjectEmpty);
//
//            else if (flight.isCheckedIn()) {
//                message = String.format(getString(R.string.dashboardStatus_CheckedIn),
//                        flight.getFlightNumber());
//                getSqlHelper().UpdateFlight(flight);
//            } else {
//                message = String.format(getString(R.string.dashboardStatus_UnableToCheckIn),
//                        flight.getFlightNumber());
//                scheduleCheckin(flight, HOUR);
//            }
//
//            displayNotification(this, message);
//            mStatus.setText("");
//        } catch (Exception e1) {
//            Utility.log(e1.toString());
//            mStatus.setText(e1.getMessage());
//        }
//    }

    private void startLoginActivity() {
        Intent intent = new Intent(this, LoginActivity.class);
        startActivityForResult(intent, LOGIN_REQUEST_CODE);
    }

    protected void refresh() {

        try {
            mTopProgressBar.setVisibility(View.VISIBLE);
            GetProfileTaskFragment mGetProfileTaskFragment =
                    (GetProfileTaskFragment) getFragmentManager().findFragmentByTag(getTaskTag());

            toggleMenuState(false);
            // If the Fragment is non-null, then it is currently being
            // retained across a configuration change.
            if (mGetProfileTaskFragment == null) {
                mStatus.setText(getString(R.string.dashboardStatus_RefreshingPNR));
                mGetProfileTaskFragment = GetProfileTaskFragment
                        .newInstance(Utility.daysToSearch());
                getFragmentManager()
                        .beginTransaction()
                        .add(mGetProfileTaskFragment, getTaskTag())
                        .commitAllowingStateLoss();
            }
        } catch (Exception e) {
            Utility.log(e.toString());
            mStatus.setText(e.getMessage());
            mTopProgressBar.setVisibility(View.INVISIBLE);
        }
    }

//    private void setupAsyncLogin() {
//        if (mBroadcastCheckinReceiver == null) {
//            mBroadcastCheckinReceiver = new BroadcastReceiver() {
//                @Override
//                public void onReceive(Context context, Intent intent) {
//                    Flight flight = (Flight) intent.getSerializableExtra(EXTRA_FLIGHT);
//                    doCheckin(flight);
//                }
//            };
//            registerReceiver(mBroadcastCheckinReceiver, new IntentFilter(CHECKIN_INTENT));
//        }
//    }


//    private void processFlightsReadyForCheckin(List<Reservation> reservations) {
//
//        try {
//            if (reservations.size() > 0)
//                for (Reservation res : reservations)
//                    for (Flight flight : res.getFlights()) {
//
//                        long timeSpan = flight.getDeparture().getTime() - new Date().getTime();
//                        log(String.format(getString(R.string.dashboardLog_ScheduleCheckIn),
//                                flight, String.valueOf(flight.isCheckedIn()), timeSpan));
//
//                        if (timeSpan <= DAY && !flight.isCheckedIn())
//                            doCheckin(flight);
//                        else if (timeSpan > DAY && timeSpan < DAY * 2 && !flight.isCheckedIn())
//                            scheduleCheckin(flight, timeSpan - DAY + MINUTE);
//                    }
//        } catch (Exception e) {
//            log(e, this);
//        }
//    }

//    private void doCheckin(Flight flight) {
//        try {
//            String tag = CHECKIN_TASK_TAG + String.valueOf(flight.getFlightNumber());
//            CheckinTaskFragment mCheckinTaskFragment =
//                    (CheckinTaskFragment) getFragmentManager().findFragmentByTag(tag);
//
//            // If the Fragment is non-null, then it is currently being
//            // retained across a configuration change.
//            if (mCheckinTaskFragment == null) {
//                mCheckinTaskFragment = CheckinTaskFragment.newInstance(flight);
//                getFragmentManager().beginTransaction().add(mCheckinTaskFragment, tag).commitAllowingStateLoss();
//            }
//        } catch (Exception e) {
//            Utility.log(e.toString());
//            mStatus.setText(e.getMessage());
//        }
//    }

//    private void scheduleCheckin(Flight flight, long timeSpan) {
//
//        try {
//            log(String.format(getString(R.string.dashboardLog_ScheduleCheckInDate),
//                    flight.toString(),
//                    (int) timeSpan,
//                    new Date(new Date().getTime() + timeSpan)));
//
//            if (flight.isCheckInScheduled()) {
//                log(String.format(getString(R.string.dashboardLog_CheckInScheduled)));
//                return;
//            }
//
//            Intent intent = new Intent(CHECKIN_INTENT);
//            intent.putExtra(EXTRA_FLIGHT, flight);
//            try {
//                mPendingCheckinIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
//                mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
//                        SystemClock.elapsedRealtime() + timeSpan,
//                        mPendingCheckinIntent);
//                flight.setIsCheckInScheduled(true);
//                getSqlHelper().UpdateFlight(flight);
//                String message = String.format(getString(R.string.dashboardToast_SchedulingToCheckIn),
//                        flight.getDeparture(),
//                        flight.getFlightNumber());
//                Toast.makeText(mContext, message, Toast.LENGTH_LONG).show();
//            } catch (Exception e) {
//                e.printStackTrace();
//                log(e.toString());
//            }
//        } catch (Exception e) {
//            Utility.log(e.toString());
//            mStatus.setText(e.getMessage());
//        }
//    }

    private void setupAsyncPnrRefresh() {
        if (mBroadcastPnrRefreshCheckinReceiver == null) {
            mBroadcastPnrRefreshCheckinReceiver = new BroadcastReceiver() {
                @Override
                public void onReceive(Context context, Intent intent) {
                    refresh();
                }
            };
            registerReceiver(mBroadcastPnrRefreshCheckinReceiver, new IntentFilter(PNR_REFRESH_INTENT));
        }
    }

    private void schedulePnrRefresh(Date date) {

        try {

            if (!Utility.pnrRefreshEnabled()) return;

            String message = String.format(getString(R.string.dashboardToast_SchedulingNextPNRRefresh), SHORT_TIME.format(date));

            log(message);

            Intent intent = new Intent("PNR_REFRESH_INTENT");
            try {
                mPendingPnrRefreshIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
                mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
                        SystemClock.elapsedRealtime() + Integer.valueOf(Utility.pnrRefreshInterval()) * HOUR,
                        mPendingPnrRefreshIntent);
                Utility.pnrRefreshDate = new Date();
                Toast.makeText(mContext, message, Toast.LENGTH_LONG).show();
            } catch (Exception e) {
                log(e.toString());
            }
        } catch (Exception e) {
            Utility.log(e.toString());
            mStatus.setText(e.getMessage());
        }
    }

    protected String getTaskTag() {
        return "myFlightsListActivityTag";
    }

}
